package com.cy.jt.jt.security.config;

import com.cy.jt.jt.security.config.hander.DefaultAccessDeniedExceptionHandler;
import com.cy.jt.jt.security.config.hander.DefaultAuthenticationEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * 由@Configuration注解描述的类为spring中的配置类,配置类会在spring
 * 工程启动时优先加载,在配置类中通常会对第三方资源进行初始化配置
 *
 * @EnableGlobalMethodSecurity 注解由SpringSecurity提供, 用于
 *  描述权限配置类,告诉系统底层在启动时,进行访问权限的初始化配置
 *  1)Enable-启用
 *  2)Global-全局
 *  3)Method-方法
 *  4)Security-安全
 */
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     *  @Bean  注解通常会在@Configuration 注解描述的类中描述方法,
     *  用于告诉spring框架这个方法的返回值交给spring管理,并给对象起个默认的名字,这个名字与方法名相同
     *  @Bean注解起名
     * @return
     */
    @Bean//对象名默认为方法名
    //@Bean("bcryptPasswordEncoder")//bean对象名字为bcryptPasswordEncoder
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**对http请求的安全控制进行配置*/
    @Override
    public void configure(HttpSecurity http) throws Exception{
        //super.configure(http)
        //1.关闭跨域
        http.csrf().disable();
        //2.配置登陆url(登陆表单使用哪个页面)
        http.formLogin()
                .loginPage("/login.html")//登录页面
                .loginProcessingUrl("/login") //设置登陆请求处理地址(对应form表单中的action),登陆时会访问UserDetailService对象
                //.usernameParameter("username")//与form表单中input元素的name属性相同
                //.passwordParameter("password")//与form表单中input元素的name属性相同
                //.successForwardUrl("/index");//请求转发(controller中的一个方法)
                //.successHandler(new JsonRedirectAuthenticationSuccessHandler())//登陆成功
                //.failureHandler(new DefaultAuthenticationFailureHandler());//登陆不成功
                .defaultSuccessUrl("/index.html");//登录成功的url(redirect)登陆成功重定向的页面
                //.successHandler(new RedirectAuthenticationSuccessHandler("http://www.tedu.cn"));
                //.failureUrl("/login.html?error");//登陆失败访问的页面（默认为/login.html?error）
        http.logout().logoutUrl("/logout").logoutSuccessUrl("/logout.html?logout");//退出操作
        //设置需要认证与拒绝访问的异常处理器
        http.exceptionHandling()
            .authenticationEntryPoint( new DefaultAuthenticationEntryPoint())//没有认证时执行DefaultAuthenticationEntryPoint对象
            .accessDeniedHandler(new DefaultAccessDeniedExceptionHandler());//没有授权时执行DefaultAccessDeniedExceptionHandler对象

        //3.放行登陆url(不需要认证就可以访问)
        http.authorizeRequests().antMatchers("/login.html")//需要放行的资源
                                .permitAll()//允许直接访问
                                .anyRequest()
                                .authenticated();//设置需要认证的请求（除了上面的要放行，其它都要进行认证）
    }
}
